/**
 * @类名称:Pay.java
 * @时间:2017年6月5日上午11:55:46
 * @作者:lihai
 * @版权:微辰金服有限公司 Copyright (c) 2017
 */
package cn.vcjf.weapp.api.payment.qfwxpay.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.springframework.stereotype.Component;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

/**
 * 订单回调抽象类
 * @param <T> 支付订单
 * @param <R> 退款订单
 */
@Component
public abstract class AbstractQfCallBackService<T,R> {

    private static Logger logger = LogManager.getLogger(AbstractQfCallBackService.class);

    /**
     * 支付回调接口入口
     * @param request
     * @param response
     * @throws IOException
     */
    public void doCallBack(HttpServletRequest request, HttpServletResponse response) throws IOException {
        setHttpServletContent(request, response);
        try {
            String result = this.invokeCallback(request);
            response.getWriter().write(result);
        } catch (Exception e) {
            logger.error("钱方支付回调接口异常", e);
            response.getWriter().write("FAIL");
        }
    }

    /**
     * 支付回调业务处理
     * @param request
     * @return
     * @throws IOException
     */
    private String invokeCallback(HttpServletRequest request) {

        JSONObject notifyJson;
        try {
            logger.info("钱方支付回调业务处理开始.");
            ServletInputStream inputStream = request.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
            StringBuffer resContent = new StringBuffer("");
            String temp = null;
            while ((temp = br.readLine()) != null) {
                resContent.append(temp);
            }
            br.close();
            logger.info("监听到收款钱方支付结果通知:{}", JSON.toJSONString(resContent.toString()));
            if (StringUtils.isEmpty(resContent.toString())) {
                return "FAIL";
            }
            notifyJson = JSONObject.parseObject(resContent.toString());
            //vc订单号
            String orderNo = notifyJson.getString("out_trade_no");
            // notify_type 通知类型
            //payment：支付； refund：退款； close：关闭；
            String type = notifyJson.getString("notify_type");
            if (StringUtils.isEmpty(orderNo)) {
                return "FAIL";
            }
            //钱方支付回调路由,根据支付类型
            /*payType 支付类型
                支付宝扫码:800101； 支付宝反扫:800108；支付宝服务窗：800107；
                微信扫码:800201； 微信刷卡:800208； 微信公众号支付:800207；*/
//            String payType = notifyJson.getString("pay_type");
            boolean orderPayFlag = true;
            {
                //支付订单
                T order = null;
                R rOrder = null;
                if("payment".equals(type)){
                    order = findOrderByOrderNo(orderNo);
                    if (null == order) {
                        logger.error("未找到订单号{}", orderNo);
                        return "FAIL";
                    }
                    if (getOrderFinishStatus().contains(getOrderStatus(order)) || getOrderStatus(order) == getOrderOkStatus()
                            || getOrderStatus(order) == getOrderFailedStatus()) {
                        return "SUCCESS";
                    }
                    String status = notifyJson.getString("status");
                    String code = notifyJson.getString("cancel");
                    if ("1".equals(status)) {
                        if("0".equals(code)){
                            updateOrderSuccess(order,  "支付成功",resContent.toString());

                        }
                        if("2".equals(code)){
                            updateOrderRefund(order,  "已退款",resContent.toString());
                            orderPayFlag=false;
                        }
                    }else {
                        updateOrderFailed(order,  "支付失败",resContent.toString());
                        orderPayFlag=false;
                    }
                //退款订单
                }else if("refund".equals(type)){
                    rOrder = findRefOrderByOrderNo(orderNo);
                    if (null == order) {
                        logger.error("未找到订单号{}", orderNo);
                        return "FAIL";
                    }
                    if (getRefOrderStatus(rOrder) == getRefOrderOkStatus() || getRefOrderStatus(rOrder) == getRefOrderFailedStatus()) {
                        return "SUCCESS";
                    }
                    String respcd = notifyJson.getString("respcd");
                    if("0000".equals(respcd)){
                        updateRefOrderRefundOk(rOrder,  "已退款",resContent.toString());
                    }else{
                        updateRefOrderRefundFailed(rOrder,  "退款失败",resContent.toString());
                        orderPayFlag=false;
                    }
                }
                try {
                    doAfterCallback(orderPayFlag,order,rOrder);
                } catch (Exception e2) {
                    logger.info("QF支付回调处理异常:",e2);
                    return "FAIL";
                }
                return "SUCCESS";
            }
        } catch (Exception e) {
            logger.error("监听钱方支付结果处理异常", e);
            return "FAIL";
        } finally {
            logger.info("钱方支付通知回调处理完成{}");
        }
    }

    protected abstract void updateRefOrderRefundFailed(R order, String orderDes, String allRes);

    /**
     * 退款订单失败状态
     * @return
     */
    protected abstract int getRefOrderFailedStatus();

    protected abstract int getRefOrderOkStatus();

    protected abstract int getRefOrderStatus(R order);

    protected abstract void updateRefOrderRefundOk(R order, String orderDes, String allRes);

    /**
     * 根据订单id获取退款订单
     * @param orderNo
     * @return
     */
    protected abstract R findRefOrderByOrderNo(String orderNo);

    protected abstract void doAfterCallback(boolean orderPayFlag,T order,R rOrder);

    protected abstract T findOrderByOrderNo(String orderNo) ;

    protected abstract int getOrderStatus(T order);
    protected abstract int getOrderOkStatus();

    /**
     * 订单完成的状态,不需要处理的状态
     * @return
     */
    protected abstract List<Integer> getOrderFinishStatus();

    protected abstract int getOrderFailedStatus();

    protected abstract int updateOrderSuccess(T order, String orderDes,String allRes);
    protected abstract int updateOrderFailed(T order, String orderDes,String allRes);
    protected abstract int updateOrderRefund(T order, String orderDes, String toString);

    public void setHttpServletContent(HttpServletRequest request, HttpServletResponse response) throws IOException {
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
    }
}
